package com.sunday.common.core.remoting.base.response;

import com.sunday.common.core.enums.ErrorCodeEnum;
import com.sunday.common.core.enums.SuccessCodeEnum;
import com.sunday.common.core.gson.GsonUtils;
import com.sunday.common.core.utils.ReflectToJsonUtils;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.lang.Nullable;

import java.io.Serializable;
import java.util.Optional;

/**
 * 系统响应
 *
 * @author zsy
 * @since 2022/10/14
 */
@Data
public class Response<T> implements Serializable {

    private Response() {
    }

    /**
     * 错误码
     */
    private String errorCode;

    /**
     * 错误信息
     */
    private String errorMessage;

    /**
     * 返回数据
     */
    private T body;

    /**
     * 返回成功消息
     *
     * @return {@link Response<T>}
     */
    public static <T> Response<T> ok() {
        return ok(null);
    }

    public static <T> Response<T> ok(@Nullable T body) {
        return resultReturn(SuccessCodeEnum.SUCCESS.errorCode, SuccessCodeEnum.SUCCESS.errorMessage, body);
    }

    /**
     * 返回失败消息
     *
     * @param errorCodeEnum
     * @return {@link Response<T>}
     */
    public static <T> Response<T> error(ErrorCodeEnum errorCodeEnum) {
        return resultReturn(errorCodeEnum, null);
    }

    /**
     * 返回失败消息
     *
     * @param errorCodeEnum
     * @param errorMessage  当这个值存在时，将会替换掉errorCodeEnum中的errorMessage消息
     * @return {@link Response<T>}
     */
    public static <T> Response<T> error(ErrorCodeEnum errorCodeEnum, @Nullable String errorMessage) {
        return error(errorCodeEnum, errorMessage, false);
    }

    public static <T> Response<T> error(ErrorCodeEnum errorCodeEnum, @Nullable String errorMessage, boolean isAppend) {
        assert errorCodeEnum != null : "errorCodeEnum must not be null";
        errorMessage = Optional.ofNullable(errorMessage)
                .filter(StringUtils::isNotBlank)
                .map(m -> isAppend ? errorCodeEnum.errorMessage + "(" + m + ")" : m)
                .orElse(errorCodeEnum.errorMessage);
        return resultReturn(errorCodeEnum.errorCode, errorMessage, null);
    }

    public static <T> Response<T> resultReturn(ErrorCodeEnum errorCodeEnum, @Nullable T body) {
        assert errorCodeEnum != null : "errorCodeEnum must not be null";
        return resultReturn(errorCodeEnum.errorCode, errorCodeEnum.errorMessage, body);
    }

    /**
     * 返回指定错误码及消息
     * protected 修饰的原因就是避免私自定义与系统无关的错误码，严格要求内部编写的错误码正确度
     *
     * @param errorCode
     * @param errorMessage
     * @return {@link Response<T>}
     */
    protected static <T> Response<T> resultReturn(String errorCode, String errorMessage) {
        return resultReturn(errorCode, errorMessage, null);
    }

    protected static <T> Response<T> resultReturn(String errorCode, String errorMessage, T body) {
        Response<T> header = new Response<T>();
        header.setErrorCode(errorCode);
        header.setErrorMessage(errorMessage);
        header.setBody(body);
        return header;
    }

    /**
     * 调用是否失败
     *
     * @return {@link boolean}
     */
    public boolean isFailure() {
        return !isSuccess();
    }

    /**
     * 调用是否成功
     *
     * @return {@link boolean}
     */
    public boolean isSuccess() {
        return SuccessCodeEnum.SUCCESS.errorCode.equals(this.errorCode);
    }

    /**
     * json 输出信息
     *
     * @return {@link String}
     */
    public String toJson() {
        return GsonUtils.DEFAULT.toJson(this);
    }

    /**
     * 优化打印
     *
     * @return {@link String}
     */
    @Override
    public String toString() {
        return ReflectToJsonUtils.toJson(this);
    }

}
